/*=====================================================================

  File:      ConnectDlg.cs
  Summary:   Dialog used to collect information to connect to a SQL Server database
  Date:	     May 27, 2006

---------------------------------------------------------------------

  This file is part of the Microsoft SQL Server Code Samples.
  Copyright (C) Microsoft Corporation.  All rights reserved.

This source code is intended only as a supplement to Microsoft
Development Tools and/or on-line documentation.  See these other
materials for detailed information regarding Microsoft code samples.

THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

======================================================= */

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Data.Sql;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Microsoft.Samples.SqlServer.DB3D
{
    // This dialog class allows users to specify how to connect to 
    // a SQL Server database. The class uses the data-source enumerator
    // to dynamically discover the SQL Server instances available in
    // the network; it also uses the schema API to find out the databases
    // available in a given server.

    public partial class ConnectDlg : Form
    {
		string _server = "(local)";
		string _database;
		bool _integratedSecurity = true;
		string _userId;
		string _password;
        
        public ConnectDlg() {
            InitializeComponent();
        }

        #region UI handling

        private void ConnectDlg_Load(object sender, EventArgs e) {
			cmbServer.Text = _server;
			cmbDatabase.Text = _database;
            rbIntegratedAuth.Checked = _integratedSecurity;
			txtUserID.Text = _userId;
			txtPassword.Text = _password;
        }
        
        private void btnOK_Click(object sender, EventArgs e) {
			// if the server field is empty, set _server to null to indicate
			// local server
			_server = cmbServer.Text.Length == 0 ? null : cmbServer.Text;

			// if the database field is empty, set _database to null to indicate
			// "default database"
			_database = cmbDatabase.Text.Length == 0 ? null : cmbDatabase.Text;

            // update the security-info related fields
			_integratedSecurity = rbIntegratedAuth.Checked;
			if(_integratedSecurity) {
                _userId = null;
                _password = null;
			}
			else {
                _userId = txtUserID.Text;
                _password = txtPassword.Text;
            }
        }

        void EnableUserID() {
            txtUserID.Enabled = rbSqlAuth.Checked;
            txtPassword.Enabled = rbSqlAuth.Checked;
        }

        private void rbIntegratedAuth_CheckedChanged(object sender, EventArgs e) {
            EnableUserID();
        }

        private void rbSqlAuth_CheckedChanged(object sender, EventArgs e) {
            EnableUserID();
        }

        private void btnRefreshServers_Click(object sender, EventArgs e) {
            // searching from the list of available SQL Servers in the
            // network is a slow operation, so we don't do it by 
            // default when the user drops-down the combo-box; instead,
            // we do it when the user explicitly clicks on the "refresh"
            // button
            LoadServersList();
        }

        private void cmbDatabase_DropDown(object sender, EventArgs e) {
            LoadDatabasesList();
        }

        #endregion

        #region Public API for the dialog
		
        public string Server {
			get { return _server; }
			set { _server = value; }
		}

		public string Database {
			get { return _database; }
			set { _database = value; }
		}

		public bool UseIntegratedSecurity {
			get { return _integratedSecurity; }
			set { _integratedSecurity = value; }
		}

		public string UserId {
			get { return _userId; }
			set { _userId = value; }
		}

		public string Password {
			get { return _password; }
			set { _password = value; }
		}

        #endregion

		#region Database-related code

		// load the list of available servers in the network
		// (note that some servers may be his option disabled and may 
		// not show up in this list)
		void LoadServersList() {
			try {
				// this may take a while, change the mouse pointer
				// to an hourglass
				UseWaitCursor = true;

				// clear previous contents
				cmbServer.Items.Clear();
				cmbServer.Items.Add("(local)");

				// obtain the list of available servers in this network
				DataTable servers = SqlDataSourceEnumerator.Instance.GetDataSources();
				
				// cache the column indexes
				int nameIndex = servers.Columns.IndexOf("ServerName");
				int instanceIndex = servers.Columns.IndexOf("InstanceName");

				// load data into the combo-box
				foreach(DataRow serverRow in servers.Rows) {
					// we're interested in two columns: the server name and the
					// instance name. If the instance name is different from
					// "MSSQLSERVER", then we have to include it in the name
                    if (!(serverRow[instanceIndex].Equals(DBNull.Value)))
                    {
                        if ("MSSQLSERVER".Equals((string)serverRow[instanceIndex], StringComparison.CurrentCultureIgnoreCase))
                            cmbServer.Items.Add(serverRow[nameIndex]);
                        else
                            cmbServer.Items.Add(serverRow[nameIndex] + "\\" + serverRow[instanceIndex]);
                    }
				}
			}
			finally {
				UseWaitCursor = false;
			}
		}

		// load the list of databases in the currently selected server
		// into the "databases" combo-box
		void LoadDatabasesList() {
			try {
				// this may take a while, change the mouse pointer
				// to an hourglass
				UseWaitCursor = true;

				// clear previous contents
				cmbDatabase.Items.Clear();

				// build a connection string based on server name and
				// authentication information from the dialog
				// Use DbConnectionString to safely add name/value pairs
                SqlConnectionStringBuilder csbuilder = new SqlConnectionStringBuilder();
				if(cmbServer.Text.Length > 0)
                    csbuilder.DataSource = cmbServer.Text;
				if(rbIntegratedAuth.Checked)
                    csbuilder.IntegratedSecurity = true;
                else {
                    csbuilder.UserID = txtUserID.Text;
                    csbuilder.Password = txtPassword.Text;
                }

                // don't want this connection to be long-lived
                csbuilder.Pooling = false;

				// connect to the server
				// the "using" keyword will make sure the connection is closed
				// after we leave the blobk
				using(SqlConnection conn = new SqlConnection(csbuilder.ToString())) {
					conn.Open();

                    // use the schema API to get the list of databases
                    DataTable databases = conn.GetSchema("Databases");

                    foreach(DataRow row in databases.Rows) {
                        cmbDatabase.Items.Add(row["database_name"]);
                    }
				}
			}
			catch(SqlException sqlex) {
				MessageBox.Show(this,
					string.Format("Failed to obtain the list of databases: {0} ({1})",
								  sqlex.Message, sqlex.Number),
					"Databases", MessageBoxButtons.OK, MessageBoxIcon.Error);
			}
			finally {
				UseWaitCursor = false;
			}
		}
		
		#endregion

    }
}